﻿using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace SharpSoft.Web
{
    public static class RazorPageExtension
    {
        /// <summary>
        /// 显示ModelState的验证消息
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="page"></param>
        /// <returns></returns>
        public static HtmlString RenderValidationMessage(this IHtmlHelper html)
        {
            StringBuilder sb = new StringBuilder();
            if (!html.ViewData.ModelState.IsValid)
            {
                sb.Append("<div class=\"model-errors\">");

                foreach (var item in html.ViewData.ModelState)
                {
                    foreach (var err in item.Value.Errors)
                    {
                        sb.Append($"<div for=\"{item.Key}\" class=\"alert alert-danger\" role=\"alert\">");
                        sb.Append(err.ErrorMessage);
                        sb.Append("</div>");
                    }

                }
                sb.Append("</div>");
            }
            return new HtmlString(sb.ToString());
        }
        /*
         <div class=""modal fade"" id=""exampleModalCenter"" tabindex=""-1"" role=""dialog"" aria-labelledby=""exampleModalCenterTitle"" aria-hidden=""true"">
  <div class=""modal-dialog modal-dialog-centered"" role=""document"">
    <div class=""modal-content"">
      <div class=""modal-header"">
        <h5 class=""modal-title"" id=""exampleModalLongTitle"">Modal title</h5>
        <button type=""button"" class=""close"" data-dismiss=""modal"" aria-label=""Close"">
          <span aria-hidden=""true"">&times;</span>
        </button>
      </div>
      <div class=""modal-body"">
        ...
      </div>
      <div class=""modal-footer"">
        <button type=""button"" class=""btn btn-secondary"" data-dismiss=""modal"">Close</button>
        <button type=""button"" class=""btn btn-primary"">Save changes</button>
      </div>
    </div>
  </div>
</div>
             */
        /// <summary>
        /// 输出Modal的前一部分
        /// </summary>
        /// <param name="html"></param>
        /// <param name="id"></param>
        /// <param name="title"></param>
        /// <returns></returns>
        public static HtmlString BeginBootstrapModal(this IHtmlHelper html, string id, string title, string @class = "", bool centered = true)
        {
            string m = $@"<div class=""modal fade"" id=""{id}"" data-bs-backdrop=""static"" tabindex=""-1"" role=""dialog"" aria-labelledby=""{id}Title"" aria-hidden=""true"">
<div class=""modal-dialog{(centered ? " modal-dialog-centered" : "")} modal-dialog-scrollable {@class}"" role=""document"">
<div class=""modal-content"">
<div class=""modal-header"">
<h5 class=""modal-title text-bold"" id=""{id}Title"">{html.Encode(title)}</h5>
<button type=""button"" class=""btn-close"" data-bs-dismiss=""modal"" aria-label=""Close""></button>
</div>
<div class=""modal-body"">";
            return new HtmlString(m);
        }
        /// <summary>
        /// 输出Modal的后一部分
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public static HtmlString EndBootstrapModal(this IHtmlHelper html, string onsubmitclick, string submitText = "提交", string closeText = "取消")
        {
            string m = $@"</div>
<div class=""modal-footer"">
<button type=""button"" onclick=""{onsubmitclick}"" class=""btnsubmit btn btn-primary"">{html.Encode(submitText)}</button>
<button type=""button"" class=""btn btn-secondary"" data-bs-dismiss=""modal"">{html.Encode(closeText)}</button>
</div>
</div>
</div>
</div>";
            return new HtmlString(m);
        }

        /// <summary>
        /// 输出导航链接（可自动标记active状态）
        /// </summary>
        /// <param name="html"></param>
        /// <param name="area">Area</param>
        /// <param name="controller">导航到的控制器</param>
        /// <param name="action">导航到的action</param>
        /// <param name="icon">图标</param>
        /// <param name="content">内容（可包含html标记）</param>
        /// <param name="para">路由参数：id</param>
        /// <param name="matchpara">用于匹配是否为活动链接的当前值，不指定则使用路由中的id来匹配</param>
        /// <returns></returns>
        public static HtmlString NavLink(this IHtmlHelper html, string area, string controller, string action, string icon, string content, object para = null, object matchpara = null)
        {
            var dic = html.ViewContext.RouteData.Values;
            string r_area = (dic["area"] ?? (object)"").ToString();
            string c = (dic["controller"] ?? (object)"").ToString();
            string a = (dic["action"] ?? (object)"").ToString();
            bool act = false;
            if (area.ToLower() == r_area.ToLower() && controller.ToLower() == c.ToLower() && action.ToLower() == a.ToLower())
            {
                if (para == null)
                {//链接未定义匹配路由参数
                    act = true;
                }
                else
                {
                    object p = matchpara ?? dic["id"];

                    if ($"{p}" == $"{para}")
                    {
                        act = true;
                    }
                }
            }

            return new HtmlString($@"<a href=""{(string.IsNullOrWhiteSpace(area) ? "" : ("/" + area))}/{controller}/{action}{(para == null ? "" : $"/{para}")}"" class=""nav-link {(act ? "active" : "")}""><i class=""fa {icon} nav-icon""></i>{content}</a>");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="contents"></param>
        /// <param name="id"></param>
        /// <param name="withIndicators"></param>
        /// <returns></returns>
        public static HtmlString BootstrapCarousel(this IHtmlHelper html, string[] contents, string id, bool withIndicators = true, bool withControl = true, int interval = 0)
        {
            if (contents == null)
            {
                return new HtmlString("");
            }
            var temp = new StringBuilder();
            temp.Append($@"<div id=""{id}"" class=""carousel slide"" data-ride=""carousel"" data-interval=""{(interval <= 0 ? "false" : interval.ToString())}"">");
            if (withIndicators)
            {
                temp.Append("<ol class=\"carousel-indicators\">");
                for (int i = 0; i < contents.Length; i++)
                {
                    temp.Append($"<li{(i == 0 ? " class=\"active\"" : "")} data-target=\"#{id}\" data-slide-to=\"{i}\"></li>");
                }
                temp.Append("</ol>");
            }
            temp.Append("<div class=\"carousel-inner\">");
            for (int i = 0; i < contents.Length; i++)
            {
                var item = contents[i];
                temp.Append($@"<div class=""{(i == 0 ? "active " : "")}carousel-item"">");
                temp.Append(item);
                temp.Append("</div>");
            }
            temp.Append("</div>");
            if (withControl)
            {
                temp.Append(
$@"<a class=""carousel-control-prev"" href=""#{id}"" role=""button"" data-slide=""prev"">
    <span class=""carousel-control-prev-icon"" aria-hidden=""true""></span>
    <span class=""sr-only"">Previous</span>
  </a>
  <a class=""carousel-control-next"" href=""#{id}"" role=""button"" data-slide=""next"">
    <span class=""carousel-control-next-icon"" aria-hidden=""true""></span>
    <span class=""sr-only"">Next</span>
  </a>");
                temp.Append("</div>");
            }

            return new HtmlString(temp.ToString());
        }
        private static int idseed = 0;
        /// <summary>
        /// 输出Bootstrap的表单字段
        /// </summary>
        /// <param name="html"></param>
        /// <param name="name"></param>
        /// <param name="label"></param>
        /// <param name="inputType">输入控件的类型，默认为text</param>
        /// <param name="id">指定id,为null则会自动生成一个Id</param>
        /// <param name="inputAttr">可以为input标签指定其他属性</param>
        /// <returns></returns>
        public static HtmlString BootstrapInputField(this IHtmlHelper html, string name, string label, string inputType = "text", string id = null,string inputAttr=null)
        {
            if (id == null)
            {
                id = $"f_{idseed++}_{name}";
            }
            var temp = new StringBuilder();
            temp.Append($@"<div class=""mb-2""><label for=""{id}"" class=""col-form-label"">{label}</label><input type=""{inputType}"" class=""form-control"" id=""{id}"" name=""{name}"" {inputAttr}/></div>");


            return new HtmlString(temp.ToString());
        }

        /// <summary>
        /// 生成分页导航
        /// </summary>
        /// <param name="html"></param>
        /// <param name="pageCount">总页数</param>
        /// <param name="curPage">当前页</param>
        /// <param name="url">跳转得到url模板，如:"/home/index?pageindex={0}",占位符{0}将被替换成实际的页索引</param>
        /// <param name="maxVisibleCount"></param>
        /// <returns></returns>
        public static HtmlString BootstrapPagination(this IHtmlHelper html, int pageCount, int curPage, string url, int maxVisibleCount = 20)
        {
            bool canpre = true, cannext = true;
            if (pageCount < 1)
            {
                return new HtmlString("");
            }
            if (maxVisibleCount < 5)
            {
                return new HtmlString("<span class=\"badge badge-danger\">可见得到页面数量不能小于5</span>");
            }
            if (curPage < 1)
            {
                curPage = 1;
            }
            if (curPage > pageCount)
            {
                curPage = pageCount;
            }

            if (curPage == 1)
            {
                canpre = false;
            }
            else if (curPage == pageCount)
            {
                cannext = false;
            }

            StringBuilder sb = new StringBuilder();
            sb.Append("<nav aria-label=\"Page navigation example\">");
            sb.Append("<ul class=\"pagination\">");

            sb.Append($"<li class=\"page-item {(canpre ? "" : "disabled")}\">");
            sb.Append($"<a class=\"page-link\" href=\"{string.Format(url, curPage - 1)}\" aria-label=\"Previous\">");
            sb.Append("<span aria-hidden=\"true\">&laquo;</span>");
            sb.Append("<span class=\"sr-only\">Previous</span>");
            sb.Append("</a></li>");


            List<int> pgs = new List<int>(maxVisibleCount);

            if (pageCount <= maxVisibleCount + 1)
            {
                for (int i = 1; i <= pageCount; i++)
                {
                    pgs.Add(i);
                }
            }
            else
            {
                var half = maxVisibleCount / 3;
                for (int i = 1; i <= half; i++)
                {
                    pgs.Add(i);
                }

                for (int i = Math.Max(curPage - half / 2, pgs.Count + 1); i <= Math.Min(curPage + half / 2, pageCount); i++)
                {
                    pgs.Add(i);
                }

                for (int i = Math.Max(pageCount - half, pgs[pgs.Count - 1] + 1); i <= pageCount; i++)
                {
                    pgs.Add(i);
                }
            }

            int last = 0;
            foreach (var item in pgs)
            {
                if (item != last + 1)
                {//跳格显示省略号
                    sb.Append($"<li class=\"page-item disabled\"><a class=\"page-link\" href=\"#\">...</a></li>");
                }
                sb.Append($"<li class=\"page-item {(item == curPage ? "active" : "")}\"><a class=\"page-link\" href=\"{string.Format(url, item)}\">{item}</a></li>");
                last = item;
            }

            sb.Append($"<li class=\"page-item {(cannext ? "" : "disabled")}\">");
            sb.Append($"<a class=\"page-link\" href=\"{string.Format(url, curPage + 1)}\" aria-label=\"Next\">");
            sb.Append("<span aria-hidden=\"true\">&raquo;</span>");
            sb.Append("<span class=\"sr-only\">Next</span>");
            sb.Append("</a></li>");
            sb.Append("</ul></nav>");
            return new HtmlString(sb.ToString());
        }


        /// <summary>
        /// 将对象的json序列化数据打印到前端
        /// </summary>
        /// <param name="html"></param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static HtmlString PrintJObject(this IHtmlHelper html, object obj)
        {
            var str = Newtonsoft.Json.JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.None);
            return new HtmlString(str);
        }
        /// <summary>
        /// 打印JS字符串
        /// </summary>
        /// <param name="html"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        public static HtmlString PrintJSString(this IHtmlHelper html, string str, char quto)
        {
            if (str == null)
            {
                return new HtmlString("null");
            }
            //StringBuilder sb = new StringBuilder();
            //foreach (var c in str)
            //{
            //    var bys = System.Text.Encoding.Unicode.GetBytes(new char[] { c });
            //    sb.Append($"\\u{bys[1]:X2}{bys[0]:X2}");
            //}
            var result = System.Text.Encodings.Web.JavaScriptEncoder.Default.Encode(str);
            return new HtmlString($"{quto}{result}{quto}");
        }
    }
}
